package com.espirit.smc.server;

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Instant;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.espirit.file.OperateKind;
import com.espirit.smc.CompareResult;

public class CompareTask  implements Callable<List<CompareResult>>{
	
	private static final Logger logger =  LoggerFactory.getLogger(CompareTask.class);
	
	private Path root;
	
	private Path path;
	
	private Map<String, Instant> fileList;
	
	private Boolean ignoreSubDir = Boolean.FALSE;
	
	public CompareTask(Path root,Path path,Map<String, Instant> fileList){
		this.root = root;
		this.path = path;
		this.fileList   = fileList;
	}
	
	public CompareTask(Path root,Path path,Map<String, Instant> fileList,Boolean ignoreSubDir){
		this.root = root;
		this.path = path;
		this.fileList   = fileList;
		this.ignoreSubDir = ignoreSubDir;
	}

	@Override
	public List<CompareResult> call() throws Exception {
		List<CompareResult> results = new LinkedList<CompareResult>();
		Files.walkFileTree(path, new SimpleFileVisitor<Path>(){
			
			@Override
			public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
				Path absolutePath = Files.isSymbolicLink(file) ? file.toRealPath() : file.toAbsolutePath();
				Path relativizePath = root.relativize(absolutePath);
				Instant lastModifiedTime = attrs.lastModifiedTime().toInstant();
				Instant lastUpdateTime = fileList.get(relativizePath.toString().replace("\\", "/"));
				CompareResult result = new CompareResult();
				result.setPath(relativizePath.toString().replace("\\", "/"));
				result.setModifyTime(Date.from(lastModifiedTime));
				if (lastUpdateTime == null) {
					result.setKind(OperateKind.CREATE);
				}else if (lastModifiedTime.isAfter(lastUpdateTime)) {
					result.setKind(OperateKind.MODIFY);
				}else if (lastModifiedTime.isBefore(lastUpdateTime)){
					result.setKind(OperateKind.OUTDATED);
				}else {
					result.setKind(OperateKind.UNCHAGE);
				}
				results.add(result);
				logger.info("Visit file :" + relativizePath.toString()+"\t lastUpdateTime : " + lastModifiedTime);
				return FileVisitResult.CONTINUE;
			}
			
			@Override
			public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
				logger.info("Visit directory :" + dir.toString());
				FileVisitResult result;
				if (!dir.equals(path) && ignoreSubDir) {
					result = FileVisitResult.SKIP_SUBTREE;
				}else {
					result = FileVisitResult.CONTINUE;
				}
				return result;
			}
		});
		
		return results;
	}

}
